﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Xml.XPath;
using HtmlAgilityPack;
using BLLTZS.Funcionalidad;
using System.Configuration;
using BLLTZS;


namespace PruebasExtraccion
{
    class Program
    {
        private static List<OfertaReelevada> _ofertas;

        static void Main(string[] args)
        {
            RobarOfertas();
            Migrar(OfertaReelevada.Abrir("LoteCache.xml"));
            Console.ReadKey();
        }

        public static void RobarOfertas()
        {
            int total = int.Parse(ConfigurationSettings.AppSettings["OfertasTotal"]);
            int contados = 0;
            bool esHoraDePartir = false;
            int pagina = 1;
            _ofertas = new List<OfertaReelevada>();
            Console.Title = "ROBANDO OFERTAS";

            do
            {
                string url;
                Console.WriteLine("Robando página " + pagina.ToString());
                if (File.Exists("RobeiraError.txt"))
                    File.Delete("RobeiraError.txt");

                try
                {
                    if (pagina == 1)
                        url = ConfigurationSettings.AppSettings["BumeranInicial"];
                    else
                        url = string.Format(ConfigurationSettings.AppSettings["BumeranVaginal"], pagina.ToString());

                    WebClient wc = new WebClient();
                    string html = wc.DownloadString(url);
                    HtmlAgilityPack.HtmlDocument documento = new HtmlAgilityPack.HtmlDocument();
                    documento.LoadHtml(html);

                    HtmlNode contenedorOfertas = documento.DocumentNode.Descendants().Where(x => (x.Name == "div" && x.Attributes["class"] != null &&
                    x.Attributes["class"].Value.Contains("span12"))).FirstOrDefault();

                    List<HtmlNode> elementosOfertas = contenedorOfertas.ChildNodes.Where(c => c.Name == "a").ToList();
                    Console.WriteLine("HECHO");

                    foreach (HtmlNode item in elementosOfertas)
                    {
                        OfertaReelevada oferta = ConvertirOferta(item);
                        if (oferta != null)
                            _ofertas.Add(oferta);

                        contados++;
                        Console.Clear();
                        Console.WriteLine("Procesadas {0}/{1}", contados, total);

                        if (contados == total)
                        {
                            esHoraDePartir = true;
                            break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    using (StreamWriter writer = new StreamWriter("Robeira.txt"))
                    {
                        writer.WriteLine("ERROR página {0}", pagina);
                        writer.WriteLine(ex.Message);
                        writer.WriteLine(ex.StackTrace);
                        writer.WriteLine();
                        writer.WriteLine();
                    }   
                }
                
                pagina++;
            } while (!esHoraDePartir);

            if (ConfigurationSettings.AppSettings["Cachear"].Equals("true"))
            {
                try
                {
                    OfertaReelevada.Guardar("LoteCache.xml", _ofertas);
                    Console.WriteLine("CACHEADO");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("ERROR CACHEANDO:");
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                }
            }
            else
                foreach (OfertaReelevada oferta in _ofertas)
                    Console.WriteLine(oferta.Titulo);
        }

        private static string ExtraerCampoTablita(string nombreEtiqueta, bool equal, List<HtmlNode> filas)
        {
            string valor = string.Empty;

            foreach (HtmlNode fila in filas)
            {
                HtmlNode etiqueta = fila.Descendants().Where(n => n.Name == "th").ToList().FirstOrDefault();

                if ((equal && etiqueta.InnerText.TrimEnd().TrimStart().Equals(nombreEtiqueta))
                    || (!equal && etiqueta.InnerText.TrimEnd().TrimStart().Contains(nombreEtiqueta)))
                {
                    HtmlNode valorElemento = fila.Descendants().Where(n => n.Name == "td").ToList().FirstOrDefault();
                    valor = ProcesarNombre(valorElemento.InnerText.TrimEnd().TrimStart());
                    break;
                }
            }

            return valor;
        }

        private static OfertaReelevada ConvertirOferta(HtmlNode elementoOferta)
        {
            OfertaReelevada oferta = new OfertaReelevada();
            string url = "[PIJA]";

            try
            {
                Console.WriteLine("Cargando próxima oferta...");
                url = ConfigurationSettings.AppSettings["Bumeran"] + elementoOferta.Attributes["href"].Value.Trim();
                WebClient wc = new WebClient();
                string html = wc.DownloadString(url);
                byte[] bytes = Encoding.Default.GetBytes(html);
                html = Encoding.UTF8.GetString(bytes);

                HtmlAgilityPack.HtmlDocument documento = new HtmlAgilityPack.HtmlDocument();
                documento.LoadHtml(html);
                Console.WriteLine("Cargada. Leyendo datos...");

                HtmlNode contenedorOferta = documento.DocumentNode.Descendants().Where(n => n.Name == "div" && n.Attributes["class"] != null && n.Attributes["class"].Value == "span-two-thirds").FirstOrDefault();

                HtmlNode contenedorImagenOferente = contenedorOferta.Descendants().Where(n => n.Name == "div" && n.Attributes["class"] != null && n.Attributes["class"].Value == "aviso-logo-empresa pull-right").FirstOrDefault();
                HtmlNode imagenOferente = contenedorImagenOferente.Descendants().Where(n => n.Name == "img").FirstOrDefault();

                if (imagenOferente == null)
                    oferta.ImagenOferente = "/css/img/sin-logo-Bumeran.jpg";
                else
                    oferta.ImagenOferente = imagenOferente.Attributes["src"].Value;

                HtmlNode contenedorTitulo = contenedorOferta.Descendants().Where(n => n.Name == "div" && n.Attributes["class"] != null && n.Attributes["class"].Value == "box").FirstOrDefault();
                HtmlNode hacheDosTitulo = contenedorTitulo.Descendants().Where(n => n.Name == "h2").FirstOrDefault();
                oferta.Titulo = hacheDosTitulo.InnerText.Trim();
                HtmlNode hacheTresOferente = contenedorTitulo.Descendants().Where(n => n.Name == "h3").FirstOrDefault();
                oferta.Oferente = hacheTresOferente.InnerText.Trim();

                HtmlNode tablaDatos = contenedorOferta.Descendants().Where(n => n.Name == "table" && n.Attributes["class"] != null && n.Attributes["class"].Value == "aviso-resumen-datos").FirstOrDefault();
                List<HtmlNode> filasTablas = tablaDatos.Descendants().Where(n => n.Name == "tr").ToList();

                oferta.FechaPublicacion = ExtraerCampoTablita("Publicado", true, filasTablas);
                oferta.Area = ExtraerCampoTablita("rea", false, filasTablas);
                oferta.TipoPuesto = ExtraerCampoTablita("Tipo de puesto", true, filasTablas);

                HtmlNode contenidoAviso = contenedorOferta.Descendants().Where(n => n.Name == "div" && n.Attributes["id"] != null && n.Attributes["id"].Value == "contenido_aviso").FirstOrDefault();
                oferta.Descripcion = System.Web.HttpUtility.HtmlDecode(contenidoAviso.InnerHtml);

                Console.WriteLine("Datos Reelevados");
            }
            catch (Exception ex)
            {
                Console.WriteLine("[¡¡¡¡¡¡¡¡¡ERROR!!!!!!!!!!!]");
                using (StreamWriter writer = new StreamWriter("RobeiraError.txt", true))
                {
                    writer.WriteLine("-------" + DateTime.Now.ToString() + "------------");
                    writer.WriteLine("URL: " + url);
                    writer.WriteLine();
                    writer.WriteLine(ex.Message);
                    writer.WriteLine();
                    writer.WriteLine(ex.StackTrace);
                    writer.WriteLine("---------------------------------------------------");
                    writer.WriteLine();
                }
                Console.WriteLine("Guardado");

                return null;
            }

            return oferta;
        }

        private static string ProcesarNombre(string nombre)
        {
            if (nombre.Contains("("))
            {
                int indice = nombre.IndexOf("(");
                nombre = nombre.Substring(0, indice);
            }
            nombre = nombre.TrimStart().TrimEnd();

            return nombre;
        }

        private static TZS_Localidad SortearLocalidad(BLLLocalidad bll)
        {
            Random ran = new Random();
            List<TZS_Localidad> localidades = bll.TraerLocalidades();
            List<TZS_Localidad> sorteadas = new List<TZS_Localidad>();

            do
            {
                int sorteo = ran.Next(0, 100);
                sorteadas = localidades.Where(l => l.Probabilidad >= sorteo).ToList();
            } while (sorteadas.Count == 0);

            int indice = ran.Next(0, sorteadas.Count - 1);

            return sorteadas[indice];
        }

        private static void Migrar(List<OfertaReelevada> ofertas)
        {
            Console.Title = "MIGRANDO LO CHOREADO";
            List<int> idsLocalidades = new BLLLocalidad().TraerLocalidades().Select(l => l.IdLocalidad).ToList();
            Random ran = new Random();
            int total = ofertas.Count;
            int contador = 0;
            int totalSinOferente = 0;
            int totalExistentes = 0;
            int totalErrores = 0;

            foreach (OfertaReelevada oferta in ofertas)
            {
                try
                {
                    contador++;
                    Console.Clear();
                    Console.WriteLine("{0}/{1}", contador, total);
                    Console.WriteLine();

                    BLLOferta bllOferta = new BLLOferta();
                    BLLLocalidad bllLocalidad = new BLLLocalidad(bllOferta.Contexto);
                    BLLTipoPuesto bllTipo = new BLLTipoPuesto(bllOferta.Contexto);
                    BLLArea bllArea = new BLLArea(bllOferta.Contexto);
                    BLLOferente bllOferente = new BLLOferente(bllOferta.Contexto);
                    Console.WriteLine("Procesando: " + oferta.Titulo);

                    if (oferta.Oferente == null || oferta.Oferente == string.Empty)
                    {
                        Console.WriteLine("Sin oferente, se omite");
                        totalSinOferente++;
                        continue;
                    }

                    if (bllOferta.Existe(oferta.Titulo))
                    {
                        Console.WriteLine("Existente, se omite");
                        totalExistentes++;
                        continue;
                    }

                    Console.WriteLine("Migrando...");

                    TZS_Oferta nuevaOferta = new TZS_Oferta();

                    nuevaOferta.Titulo = oferta.Titulo;
                    nuevaOferta.Descripcion = oferta.Descripcion;
                    nuevaOferta.Ambito = (int)Ambitos.Empresa;

                    nuevaOferta.TZS_Localidad = SortearLocalidad(bllLocalidad);

                    TZS_TipoPuesto tipo;
                    if (bllTipo.Existe(oferta.TipoPuesto))
                        tipo = bllTipo.Traer(oferta.TipoPuesto);
                    else
                    {
                        tipo = new TZS_TipoPuesto();
                        tipo.Nombre = oferta.TipoPuesto;
                        bllTipo.CargarNuevo(tipo);
                    }
                    nuevaOferta.TZS_TipoPuesto = tipo;

                    TZS_Area area;
                    if (bllArea.Existe(oferta.Area))
                        area = bllArea.Traer(oferta.Area);
                    else
                    {
                        area = new TZS_Area();
                        area.Nombre = oferta.Area;
                        bllArea.CargarNueva(area);
                    }
                    nuevaOferta.TZS_Area = area;

                    TZS_Oferente oferente;
                    if (bllOferente.Existe(oferta.Oferente))
                        oferente = bllOferente.Traer(oferta.Oferente);
                    else
                    {
                        oferente = new TZS_Oferente();
                        oferente.Nombre = oferta.Oferente;
                        oferente.Logo = oferta.ImagenOferente;
                        bllOferente.CargarNuevo(oferente);
                    }
                    nuevaOferta.TZS_Oferente = oferente;

                    bllOferta.CargarNuevaOferta(nuevaOferta);
                    bllOferta.GuardarCambios();
                    Console.WriteLine("MIGRADOs:" + contador.ToString());
                }
                catch (Exception ex)
                {
                    totalErrores++;

                    try
                    {
                        using (StreamWriter writer = new StreamWriter("Migrazao.txt", true))
                        {
                            writer.WriteLine();
                            writer.WriteLine();
                            writer.WriteLine(DateTime.Now.ToString());
                            writer.WriteLine("ERROR: " + ex.Message);
                            writer.WriteLine();
                            writer.WriteLine(ex.StackTrace);
                            writer.WriteLine();
                            writer.WriteLine();
                        }
                    }
                    catch { }
                }
            }

            Console.WriteLine("Sin Oferentes: " + totalSinOferente.ToString());
            Console.WriteLine("Existentes: " + totalExistentes.ToString());
            Console.WriteLine("Errores: " + totalErrores.ToString());
            Console.WriteLine();
            Console.WriteLine("YA ESTÁ AMIGO");
        }
    }
}
